/*                          UX-Framework                               
 *                                                                 
 *  iZE Co.,Ltd. Copyright 2009 All rights reserved.          
 *  This file is distributed under the terms of the GNU Lesser 
 *  General Public License, described in file LICENSE.
 */
package jp.ize.ux.acts;

// {{{ imports
import jp.ize.ux.tween.UXTweenManager;
import jp.ize.ux.tween.UXTween;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.FocusEvent;
import jp.ize.ux.UXObject;
import jp.ize.ux.geom.UXPoint;
import jp.ize.ux.utils.Util;
import jp.ize.iwp.utils.sync.SyncManager;
import jp.ize.iwp.utils.sync.SyncUnit;
import jp.ize.iwp.utils.sync.SyncEvent;
// }}}
/** 
 * Actクラス<br>
 * 動きを表すクラスが利用する基本的なenum, 型, クラスの集合です。<br>
 *
 * @author		iZE Co., Ltd.<br>
 * @version		$Id$<br>
 */
// {{{ typedef TPoint
typedef TPoint =
{
	x:Float,
	y:Float
}
// }}}
// {{{ typedef TPos
typedef TPos =
{
	var row:Int;
	var col:Int;
}
// }}}
// {{{ typedef BasicStateType =
typedef BasicStateType =
{
	function touch() : Void;
	function detouch() : Void;
	var target : UXObject;
	var eventTarget : Dynamic;
	var subject : Dynamic;
	var mouse : MouseEvent;
	var keyboard : KeyboardEvent;
	var focus : FocusEvent;
	var any : Dynamic;
}
// }}}
// {{{ typedef ListStateType
typedef ListStateType = {
	> BasicStateType,
	var children : Array<UXObject>;
	var cyclic : Bool;
	function iterator() : Iterator<UXObject>;
}
// }}}
// {{{ typedef ActParameter
typedef ActParameter =
{
	// {{{ var time : Float;
	/**
	 *	Actが完了するまでにかける時間(秒)です。
	 * 20fpsを基準としています。実際の秒数とは異なることがあります。
	 */
	var time : Float;
	// }}}
	// {{{ var transition : ActTransition;
	/**
	 * 移動の方法です。詳細は jp.ize.ux.twween.easings を参照してください。
	 */
	var transition : Easing;
	// }}}
}
// }}}
// {{{ typedef MoveParameter > ActParameter
/**
 * ムーブアクションが必要なパラメーターです。
 */
typedef MoveParameter =
{
	> ActParameter,
	// {{{ var delta : Int
	/**
	 * 子コンポーネントを何個分移動するかの数値です。
	 */
	var delta : Int;
	// }}}
}
// }}}
// {{{ typedef WipeParameter > ActParameter
/**
 * ワイプアクションが必要なパラメーターです。
 */
typedef WipeParameter =
{
	> ActParameter,
	// {{{ var center : Int
	/**
	 * どの子コンポーネントを中心に集めるかを指定する子コンポーネントのインデックス番号です。
	 */
	var center : Int;
	// }}}
}
// }}}
// {{{ typedef ShuffleParameter > ActParameter
/**
 * シャップルアクションが必要なパラメーターです。
 */
typedef ShuffleParameter =
{
	> ActParameter,
	// {{{ var  targets : Array<Int>
	/**
	 * シャッフルの対象になる子コンポーネントのインデックス番号の配列です。
	 */
	var  targets : Array<Int>;
	// }}}
}
// }}}
// {{{ typedef FishEyeParameter > ActParameter
/**
 * 魚眼ズームにて必要なパラメーターです。
 */
typedef FishEyeParameter =
{
	> ActParameter,
	// {{{ var  centerScale : Float
	/**
	 * 中心になる UXObject の拡大率（最大の拡大率）です
	 */
	var centerScale : Float;
	// }}}
	// {{{ var  effectRange : Int
	/**
	 * 左右に影響する範囲を指定します。片側分の要素数を指定します。
	 * たとえば、2を指定した場合は、中心から左に2つ、右に2つずつ影響を受けることになります。
	 */
	var effectRange : Int;
	// }}}
}
// }}}
// {{{ class Act
/**
 * Actクラス.<br>
 * (高階関数版)オブザーバーパターンにおける主体。
 */
class Act
{
	// {{{ properties

	public static var START : String = "start";
	public static var STOP  : String = "stop";

	public var syncDoneFunc:Void->Void;

	// {{{ public var tm:UXTweenManager;
	/**
	 * アニメーション・トゥイーン用のマネージャークラスのインスタンス保持用です。
	 */
	public var tm:UXTweenManager;

	// }}}
	// {{{ public var sync:SyncManager;
	/**
	 * アニメーション・トゥイーンの同期用です。
	 */
	public var sync:SyncManager;

	// }}}
	// {{{ public var syncs:Array<SyncUnit>;
	/**
	 * アニメーション・トゥイーンの同期用です。
	 */
	public var syncs:Array<SyncUnit>;

	// }}}
	// {{{ public var listeners : Array<Assoc<String, E->Void>>;
	/**
	 * オブザーバーを登録しておくための変数です。
	 */
	public var listeners : Array<Assoc<String, Dynamic->Void>>;

	// }}}
	// }}}
	// {{{ public static function exec( act:Dynamic->Void, s:Dynamic ) : Void
	/**
	 * 指定のアクションを実行します。
	 *
	 * @param act: アクション関数を指定します。
	 * @param s: 状態オブジェクトを指定します。
	 */
	public static function exec( act:Dynamic->Void, s:Dynamic ) : Void
	{
		act(s);
	}
	// }}}
	// {{{ public function new()
	/**
	 * コンストラクタ。
	 */
	public function new()
	{
		listeners = new Array();
		tm = new UXTweenManager();
		initSync(1);
	}
	// }}}
	// {{{ public function addListener( event : String, f : Dynamic -> Void )
	/**
	 * オブザーバーを登録する関数。指定されたイベントが発生すると、登録された関数は登録された順番に呼ばれます。
	 */
	public function addListener( event : String, f : Dynamic->Void )
	{
		listeners.push( new Assoc(event,f) );
	}
	// }}}
	// {{{ public function removeListener( event : String )
	/**
	 * 指定されたイベントのオブザーバーの登録を全て解除する関数です。
	 */
 	public function removeListener( event : String  )
	{
		var target = null;
		for ( assoc in listeners ) {
			if ( event==assoc.key() ) {
				target = assoc;
			}
		}
		if ( target!=null ) {
			listeners.remove(target);
		}
	}
	// }}}
	// {{{ public function notify( event : String )
	/**
	 * リスナーに指定されたイベントを通知します。
	 */
 	public function notify( event : String  )
	{
		var target = null;
		for ( assoc in listeners ) {
			if ( event==assoc.key() ) {
				var func = assoc.value();
				func(null);
			}
		}
	}
	// }}}
	// {{{ public function initSync( n:Int ) : Void

	public function initSync( n:Int ) : Void
	{
		if ( sync!=null ) {
			var e:SyncEvent = new SyncEvent(SyncEvent.ALL_COMPLETE,true,true);
			sync.dispatchEvent(e);
			sync.removeEventListener( SyncEvent.ALL_COMPLETE, onSyncAllComplete );
		}
		sync = new SyncManager();
		syncs = new Array();
		sync.addEventListener( SyncEvent.ALL_COMPLETE, onSyncAllComplete, false, 0, true );
		for ( i in 0...n ) {
			sync.createSyncUnit();
		}
	}

	// }}}
	// {{{ public function doneSync( i:Int ) : Void

	public function doneSync( i:Int ) : Void
	{
		sync.done(i);
	}

	// }}}
	// {{{ public function setSyncDoneHandler( f:Void->Void ) : Void

	public function setSyncDoneHandler( f:Void->Void ) : Void
	{
		syncDoneFunc = f;
	}

	// }}}
	// {{{ public function onSyncAllComplete( e:SyncEvent ) : Void

	public function onSyncAllComplete( e:SyncEvent ) : Void
	{
		if ( syncDoneFunc!=null ) syncDoneFunc();
	}

	// }}}
}
// }}}
